package org.vaadinetherealintegration.client;

import java.util.ArrayList;
import java.util.List;

import org.vaadinetherealintegration.client.example1.Example1;
import org.vaadinetherealintegration.client.example2.Example2;
import org.vaadinetherealintegration.client.example3.Example3;
import org.vaadinetherealintegration.client.example4.Example4;
import org.vaadinetherealintegration.client.example5.Example5;


import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseWheelEvent;

import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;

import etrl.camera.FirstPersonManipulator;
import etrl.core.Viewer;
import etrl.core.Viewer.EventHandlingMode;

public class VMyComponent extends Widget implements Paintable{

	/** Set the CSS class name to allow styling. */
	public final String CLASSNAME = "v-mycomponent";

	/** The client side widget identifier */
	protected String paintableId;

	private Viewer viewer;
	
	private FirstPersonManipulator fpManipulator;
	
	public static final String EXAMPLE_NUMBER = "EXAMPLE_NUMBER";
	public static final String EXAMPLE1 = "Example 1";
	public static final String EXAMPLE2 = "Example 2";
	public static final String EXAMPLE3 = "Example 3";
	public static final String EXAMPLE4 = "Example 4";
	public static final String EXAMPLE5 = "Example 5";

	public static final String EXAMPLE_NUMBER_RELOAD = "EXAMPLE_NUMBER_RELOAD";
	
	/** Reference to the server connection object. */
	ApplicationConnection client;

	ExampleInterface currentScene;

	private String exampleNumber;
	
	List<ExampleInterface> scenes = new ArrayList<ExampleInterface>();
	
	/**
	 * The constructor should first call super() to initialize the component and
	 * then handle any initialization relevant to Vaadin.
	 */
	public VMyComponent() {

		super();
		
		viewer = new Viewer(1200, 800,EventHandlingMode.MOUSE_EVENTS_ON_CANVAS);		

		fpManipulator = new FirstPersonManipulator();
		
		viewer.setCameraManipulator(fpManipulator);
						
		this.instantiateScenes();
		
		addDomHandler(viewer.getMouseHandler(), MouseDownEvent.getType());
		addDomHandler(viewer.getMouseHandler(), MouseMoveEvent.getType());
		addDomHandler(viewer.getMouseHandler(), MouseUpEvent.getType());
		addDomHandler(viewer.getMouseHandler(), MouseWheelEvent.getType());
		addDomHandler(viewer.getMouseHandler(), MouseOutEvent.getType());
		
		setElement(viewer.getCanvas().getElement());
		
		// This method call of the Paintable interface sets the component
		// style name in DOM tree
		setStyleName(CLASSNAME);
	}


	public void instantiateScenes(){
		scenes.add(new Example1(viewer));
		scenes.add(new Example2(viewer));
		scenes.add(new Example3(viewer));
		scenes.add(new Example4(viewer));
		scenes.add(new Example5(viewer));
	}
	
	private ExampleInterface getScene() {

		ExampleInterface scene = null;

		if(exampleNumber.equals(EXAMPLE1)){			
			scene = scenes.get(0);			
		}

		else if(exampleNumber.equals(EXAMPLE2)){
			scene = scenes.get(1);
		}

		else if(exampleNumber.equals(EXAMPLE3)){
			scene = scenes.get(2);

		}

		else if(exampleNumber.equals(EXAMPLE4)){
			scene = scenes.get(3);
		}
		
		else if(exampleNumber.equals(EXAMPLE5)){
			scene = scenes.get(4);
		}

		else {
			Window.alert("Rendering NOTHING "  + exampleNumber);
		}
		return scene;
	}


	/**
	 * Called whenever an update is received from the server
	 */
	public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
		// This call should be made first.
		// It handles sizes, captions, tooltips, etc. automatically.
		if (client.updateComponent(this, uidl, true)) {
			Window.alert("Return");
			// If client.updateComponent returns true there has been no changes
			// and we
			// do not need to update anything.
			return;
		}

		// Save reference to server connection object to be able to send
		// user interaction later
		this.client = client;

		// Save the client side identifier (paintable id) for the widget
		paintableId = uidl.getId();			
				
		exampleNumber = null;
		
		if(uidl.hasAttribute(EXAMPLE_NUMBER)){

			exampleNumber = uidl.getStringAttribute(EXAMPLE_NUMBER);

			currentScene = getScene();

			handleExampleNumber(exampleNumber);
		}	
		
	}
	
	private void handleExampleNumber(String exampleNumber){
		currentScene.atStart();

		viewer.setSceneData(currentScene.buildSceneRoot());

		fpManipulator.setPosition(currentScene.getInitialCameraPos());
		fpManipulator.setOrientation(currentScene.getInitialCameraOrientation());

		viewer.scheduleRepeating(10);
	}
}
